package workqueues.acknowledgment;

import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import utils.RabbitMQUtil;
import utils.SleepUtil;

import java.nio.charset.StandardCharsets;

public class Worker01 {

    public static final String TASK_QUEUE_NAME = "ack_queue";

    public static void main(String[] args) throws Exception{

        Channel channel = RabbitMQUtil.getChannel();
        System.out.println("C1等待接收消息处理时间较短");

        DeliverCallback deliverCallback = (consumerTag, message) ->{
            // 睡眠一秒钟
            SleepUtil.sleep(1);
            System.out.println("接收到的消息："+new String(message.getBody(), StandardCharsets.UTF_8));

            /**
             *  int prefetchCount = 0;
             *  prefetchCount的默认值是0，表示轮询分发消息
             *  
             *  解释如下：
             *  (1)前提：prefetchCount=0
             *  (2)两个消费者worker1 和 worker2
             *  (3)一个生产者Task不断往队列发送消息，并且发送的消息大小不一致(此处消息的大小指的是，小的消息可以被消费者快速处理，大的消息消费者要处理较长的时间)
             *  (4)模拟场景如下：
             *      1. 生产者连续发送了6个消息：1(小消息)、2(大消息)、3(小消息)、4(大消息)、5(小消息)、6(大消息)，在轮询分发时，worker1得到了消息1、3、5; worker2得到了消息2、4、6
             *          5(小消息)、3(小消息)、1(小消息) ---> worker1
             *          6(大消息)、4(大消息)、2(大消息) ---> worker2
             *      2. 此时就会出现的情况是，因为消息1、3、5都是小消息，所以分配给worker1的时候，worker1可以很快地处理完并且发送 确认应答 信息。(队列中不会积压消息)
             *         但是因为2、4、6都是大消息，当分配给worker2的时候，worker2不能很快处理这些大消息，所以也就不能很快发送 确认应答 信息。(可能导致队列中消息积压)
             */

            /**
             *  int prefetchCount = 1;
             *  prefetchCount的设置为1，可以达到不公平分发的目的(能者多劳)
             *  解释如下：
             *  (1)前提：prefetchCount=1
             *  (2)两个消费者worker1 和 worker2
             *  (3)一个生产者Task不断往队列发送消息，并且发送的消息大小不一致(此处消息的大小指的是，小的消息可以被消费者快速处理，大的消息消费者要处理较长的时间)
             *  (4)模拟场景如下：
             *      1. 生产者连续发送了6个消息：1(小消息)、2(大消息)、3(小消息)、4(大消息)、5(小消息)、6(大消息)，假设间隔1s发送一次消息
             *          5(小消息)、4(大消息)、3(小消息)、1(小消息) ---> worker1
             *          6(大消息)、2(大消息) ---> worker2
             *      2. 此处比喻的不恰当，但是我大概理解了其中的思想。
             */
            int prefetchCount = 2;
            channel.basicQos(prefetchCount);
            channel.basicAck(message.getEnvelope().getDeliveryTag(),false);
        };

        // 消息接收被取消时，执行下面的内容
        CancelCallback cancelCallback = consumerTag -> {
            System.out.println(consumerTag+"消费者取消消费接口回调逻辑");
        };
        channel.basicConsume(TASK_QUEUE_NAME, false,deliverCallback,cancelCallback);
    }
}
